package com.zahb.qadx.net;

import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.InstanceCreator;
import com.google.gson.internal.ConstructorConstructor;
import com.zahb.qadx.base.BaseApplication;
import com.zahb.qadx.model.DataLogin;
import com.zahb.qadx.net.interceptor.Code203Interceptor;
import com.zahb.qadx.net.interceptor.LoggerInterceptor;
import com.zahb.qadx.util.CompatHelper;
import com.zahb.qadx.util.JsonUtil;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import io.reactivex.schedulers.Schedulers;
import okhttp3.Cache;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

public class RetrofitService {

    static final int TYPE_ENVIRONMENT_DEBUG = 1;
    static final int TYPE_ENVIRONMENT_RELEASE = 2;
    static final int TYPE_ENVIRONMENT_DEV = 3;
    public static String TYPE_ENVIRONMENT = "1";
    private static final String BASE_URL_DEBUG = "http://47.111.14.128:8004/";// 测试环境
    private static final String BASE_URL_RELEASE = "http://121.196.44.61:8004/";// 生产环境
    private static final String BASE_URL_DEV = "http://121.40.144.72:8004/";// 预生产环境

    private static String BASE_URL = "";
    static final String BASE_URL_DIR = "";
    private static ApiService mApiService;
    private static final long CACHE_SIZE = 1024 * 1024 * 100;// 100M
    private static final long DEFAULT_CONNECT_TIME_OUT = 10L;
    private static final long DEFAULT_WRITE_TIME_OUT = 10L;
    private static final long DEFAULT_READ_TIME_OUT = 10L;
    private static final String DO_MAIN = "qian.qianuni.com";
    private static final String CONNECT_TIMEOUT = "CONNECT_TIMEOUT";
    private static final String READ_TIMEOUT = "READ_TIMEOUT";
    private static final String WRITE_TIMEOUT = "WRITE_TIMEOUT";
    private static final Gson sGson;

    static {
        if (Integer.parseInt(TYPE_ENVIRONMENT) == TYPE_ENVIRONMENT_DEBUG) {
            BASE_URL = BASE_URL_DEBUG;
        } else if (Integer.parseInt(TYPE_ENVIRONMENT) == TYPE_ENVIRONMENT_RELEASE) {
            BASE_URL = BASE_URL_RELEASE;
        } else if (Integer.parseInt(TYPE_ENVIRONMENT) == TYPE_ENVIRONMENT_DEV) {
            BASE_URL = BASE_URL_DEV;
        }

        /*
         * https://www.cnblogs.com/linjzong/p/5201565.html
         */
        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.registerTypeAdapterFactory(new CustomTypeAdapterFactory());
        //通过反射获取instanceCreators属性
        try {
            Class<?> builder = gsonBuilder.getClass();
            Field f = builder.getDeclaredField("instanceCreators");
            f.setAccessible(true);
            @SuppressWarnings({"unchecked"})
            Map<Type, InstanceCreator<?>> val = (Map<Type, InstanceCreator<?>>) f.get(gsonBuilder);//得到此属性的值
            //注册数组的处理器
            gsonBuilder.registerTypeAdapterFactory(new CollectionTypeAdapterFactory(new ConstructorConstructor(val)));
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
        sGson = gsonBuilder.create();
    }

    public static ApiService getNetService() {
        if (mApiService == null) {
            synchronized (RetrofitService.class) {
                if (mApiService == null) {
                    Interceptor timeoutInterceptor = chain -> {
                        Request request = chain.request();
                        int connectTimeout = chain.connectTimeoutMillis();
                        int readTimeout = chain.readTimeoutMillis();
                        int writeTimeout = chain.writeTimeoutMillis();

                        String connectNew = request.header(CONNECT_TIMEOUT);
                        String readNew = request.header(READ_TIMEOUT);
                        String writeNew = request.header(WRITE_TIMEOUT);

                        if (connectNew != null && connectNew.length() > 0 && TextUtils.isDigitsOnly(connectNew)) {
                            connectTimeout = Integer.parseInt(connectNew);
                        }
                        if (readNew != null && readNew.length() > 0 && TextUtils.isDigitsOnly(readNew)) {
                            readTimeout = Integer.parseInt(readNew);
                        }
                        if (writeNew != null && writeNew.length() > 0 && TextUtils.isDigitsOnly(writeNew)) {
                            writeTimeout = Integer.parseInt(writeNew);
                        }

                        return chain
                                .withConnectTimeout(connectTimeout, TimeUnit.MILLISECONDS)
                                .withReadTimeout(readTimeout, TimeUnit.MILLISECONDS)
                                .withWriteTimeout(writeTimeout, TimeUnit.MILLISECONDS)
                                .proceed(request);
                    };
                    Cache cache = new Cache(new File(BaseApplication.getContext().getCacheDir(), "NetCache"), CACHE_SIZE);

                    OkHttpClient okHttpClient = new OkHttpClient().newBuilder().cache(cache)
                            .retryOnConnectionFailure(true)
                            .addInterceptor(sCommonInterceptor)
                            .addNetworkInterceptor(new Code203Interceptor())
                            .addNetworkInterceptor(new LoggerInterceptor(LoggerInterceptor.TAG, true))
                            .addInterceptor(timeoutInterceptor)
                            .connectTimeout(DEFAULT_CONNECT_TIME_OUT, TimeUnit.SECONDS)
                            .writeTimeout(DEFAULT_WRITE_TIME_OUT, TimeUnit.SECONDS)
                            .readTimeout(DEFAULT_READ_TIME_OUT, TimeUnit.SECONDS)
                            .build();

                    /*GsonBuilder gsonBuilder = new GsonBuilder();
                    gsonBuilder.registerTypeAdapterFactory(new CustomTypeAdapterFactory());*/
                    Retrofit retrofit = new Retrofit.Builder()
                            .baseUrl(BASE_URL)
                            .client(okHttpClient)
                            .addConverterFactory(GsonConverterFactory.create(sGson))
                            .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
                            .build();

                    mApiService = retrofit.create(ApiService.class);
                }
            }
        }

        return mApiService;
    }
    /**
     * 封装公共参数
     */
    private static final Interceptor sCommonInterceptor = chain -> {
        Request oldRequest = chain.request();
        // header添加domain
        Request.Builder requestBuilder = oldRequest.newBuilder()
                .addHeader("domain", DO_MAIN);
        if (!TextUtils.isEmpty(BaseApplication.getContext().getToken())) {
            requestBuilder.addHeader("token", BaseApplication.getContext().getToken() + "")
                    .addHeader("rootOrgId", BaseApplication.getContext().getDataLogin().getCurrentOrg() + "");
        } else {
            SharedPreferences sp = BaseApplication.getContext().getSharedPreferences("AccountInfo", Context.MODE_PRIVATE);
            String loginDataStr = sp.getString("loginData", "");
            if (!CompatHelper.isEmpty(loginDataStr)) {
                DataLogin dataLogin = JsonUtil.getGson().fromJson(loginDataStr, DataLogin.class);
                BaseApplication.getContext().setDataLogin(dataLogin);
                requestBuilder.addHeader("token", BaseApplication.getContext().getToken() + "")
                        .addHeader("rootOrgId", BaseApplication.getContext().getDataLogin().getCurrentOrg() + "");
            }
        }

        return chain.proceed(requestBuilder.build());
    };
}





